home *** CD-ROM | disk | FTP | other *** search
- { Version 2.0, 1/28/86
- For MS-DOS version 2.0 or greater, Turbo Pascal 1.0 or greater.
-
- Thanks to Marshall Brain for the original idea for these routines.
- Thanks to John Cooper for pointing out a small flaw in the code.
-
- These routines provide a method for Turbo Pascal programs to trap MS-DOS
- interrupt 24 (hex). INT 24h is called by DOS when a 'critical error' occurs,
- and it normally prints the familiar "Abort, Retry, Ignore?" message.
-
- With the INT 24h handler installed, errors of this type will be passed on to
- Turbo Pascal as an error. If I/O checking is on, this will cause a program
- crash. If I/O checking is off, IOResult will return an error code. The
- global variable INT24Err will be true if an INT 24h error has occurred. The
- variable INT24ErrorCode will contain the INT 24h error code as given by DOS.
- These errors can be found in the DOS Technical Reference Manual.
- It is intended that INT24Result be used in place of IOResult. Calling
- INT24Result clears IOResult. The simple way to use INT24Result is just to
- check that it returns zero, and if not, handle all errors the same. The more
- complicated way is to interpret the code. The integer returned by INT24Result
- can be looked at as two bytes. By assigning INT24Result to a variable, you
- can then examine the two bytes: (Hi(<variable>)-1) will give the DOS critical
- error code, or (<variable> And $FF00) will return an integer from the table
- listed in the INT24Result procedure (two ways of looking at the critical
- error); Lo(<variable>) will give Turbo's IOResult. A critical error will
- always be reflected in INT24Result, but the IOResult part of INT24Result will
- not necessarily be nonzero; in particular, unsuccessful writes to character
- devices will not register as a Turbo I/O error.
-
- INT24Result should be called after any operation which might cause a
- critical error, if Turbo's I/O checking is disabled. If it is enabled, the
- program will be aborted except in the above noted case of writes to character
- devices.
-
- Also note that different versions of DOS and the BIOS seem to react to
- printer errors at vastly different rates. Be prepared to wait a while for
- anything to happen (in an error situation) on some machines.
-
- These routines are known to work correctly with: Turbo Pascal 1.00B PC-DOS;
- Turbo Pascal 2.00B PC-DOS;
- Turbo Pascal 2.00B MS-DOS;
- Turbo Pascal 3.01A PC-DOS.
- Other MS-DOS and PC-DOS versions should work.
-
- Note that Turbo 2.0's normal IOResult codes for MS-DOS DO NOT correspond to
- the I/O error numbers given in Appendix I of the Turbo 2.0 manual, or to the
- error codes given in the I/O error nn, PC=aaaa/Program aborted message. Turbo
- 3.0 IOResult codes do match the manual. Here is a table of the correspondence
- (all numbers in hexadecimal):
-
- Turbo 2.0 IOResult Turbo error, Turbo 3.0 IOResult
- ------------------ -------------------------------------------------
- 00 00 none
- 01 90 record length mismatch
- 02 01 file does not exist
- 03 F1 directory is full
- 04 FF file disappeared
- 05 02 file not open for input
- 06 03 file not open for output
- 07 99 unexpected end of file
- 08 F0 disk write error
- 09 10 error in numeric format
- 0A 99 unexpected end of file
- 0B F2 file size overflow
- 0C 99 unexpected end of file
- 0D F0 disk write error
- 0E 91 seek beyond end of file
- 0F 04 file not open
- 10 20 operation not allowed on a logical device
- 11 21 not allowed in direct mode
- 12 22 assign to standard files is not allowed
-
- - Bela Lubkin
- CompuServe 76703,3015
- 1/28/86
- }
-
- Procedure INT24;
- Const FCBFuncs: Array [1..6] Of Byte=(14,15,21,22,27,28);
- Begin
- { To understand this routine, you will need to read the description of
- Interrupt 24h in the DOS manual. It also helps to examine and trace the
- generated code under DEBUG. }
- Inline($0E/$0E/$1F/$07/$C6/$06/ INT24Err /$01/$89/$EC/$83/$C4/$08/
- $89/$F8/$A2/ INT24ErrCode /$58/$B9/$06/$00/$BF/ FCBFuncs /$F2/
- $AE/$75/$04/$B0/$01/$EB/$08/$3C/$39/$B0/$FF/$72/$02/$B0/$83/
- $5B/$59/$5A/$5E/$5F/$89/$E5/$80/$4E/$0A/$01/$5D/$1F/$07/$CF);
- { Turbo: PUSH BP (Save caller's stack frame
- MOV BP,SP Set up this procedure's stack frame
- PUSH BP ?)
- Inline: PUSH CS
- PUSH CS
- POP DS Set DS and ES temporarily to CS
- POP ES
- MOV BYTE [INT24Err],1 Set INT24Err to True (CS:)
- MOV SP,BP Get correct SP; ADD: Discard saved
- ADD SP,8 BP, INT 24h return address & flags
- MOV AX,DI Get INT 24h error code
- MOV [INT24ErrCode],AL Save it in INT24ErrCode
- POP AX Get initial DOS call number
- MOV CX,6 Search for it in FCBFuncs: is this one
- MOV DI,Offset FCBFuncs of the FCB functions that requires an
- REPNZ SCASB error code of 01 in AL?
- JNZ .1
- MOV AL,1 Yes: set it
- JMP .2
- .1 CMP AL,39h No: is it an FCB function that requires
- MOV AL,0FFh AL=FFh (function <39h)? Yes: set it.
- JB .2
- MOV AL,83h No: handle call, return error 83h, call
- failed via INT 24h.
- The error code (1, FFh or 83h) is
- returned to the Turbo runtime routine
- that called DOS, making it look like
- a simple DOS error. Turbo handles
- the I/O error.
- .2 POP BX Pop the rest of the registers saved by
- POP CX the initial INT 21h.
- POP DX
- POP SI
- POP DI
- MOV BP,SP
- OR Byte Ptr [BP+0Ah],1 Set the carry flag in the saved Flags reg.
- POP BP
- POP DS
- POP ES
- IRET Return to next instruction: all regs.
- restored, AL=error code, carry set. }
- End;
-
- Procedure INT24On; { Enable INT 24h trapping }
- Begin
- INT24Err:=False;
- With RegisterSet Do
- Begin
- AX:=$3524;
- MsDos(RegisterSet);
- If (OldINT24[1] Or OldINT24[2])=0 Then
- Begin
- OldINT24[1]:=ES;
- OldINT24[2]:=BX;
- End;
- DS:=CSeg;
- DX:=Ofs(INT24);
- AX:=$2524;
- MsDos(RegisterSet);
- End;
- End;
-
- Procedure INT24Off; { Disable INT 24h trapping. Should be done at the end of
- the program, if you plan to run the program from within
- the Turbo compiler. If the INT 24h handler is left in
- place, and the compiler gets a critical error, the
- system is likely to crash. }
- Begin
- INT24Err:=False;
- If OldINT24[1]<>0 Then
- With RegisterSet Do
- Begin
- DS:=OldINT24[1];
- DX:=OldINT24[2];
- AX:=$2524;
- MsDos(RegisterSet);
- End;
- OldINT24[1]:=0;
- OldINT24[2]:=0;
- End;
-
- Function INT24Result: Integer;
- Var
- I:Integer;
-
- Begin
- I:=IOResult;
- If INT24Err Then
- Begin
- I:=I+256*Succ(INT24ErrCode);
- INT24On;
- End;
- INT24Result:=I;
- End;
- { INT24Result returns all the regular Turbo IOResult codes if no critical
- error has occurred. If a critical error, then the following values are
- added to the error code from Turbo:
- 256: Attempt to write on write protected disk
- 512: Unknown unit [internal dos error]
- 768: Drive not ready [drive door open or bad drive]
- 1024: Unknown command [internal dos error]
- 1280: Data error (CRC) [bad sector or drive]
- 1536: Bad request structure length [internal dos error]
- 1792: Seek error [bad disk or drive]
- 2048: Unknown media type [bad disk or drive]
- 2304: Sector not found [bad disk or drive]
- 2560: Printer out of paper [anything that the printer might signal]
- 2816: Write fault [character device not ready]
- 3072: Read fault [character device not ready]
- 3328: General failure [several meanings]
-
- If you need the IOResult part, use
- I:=INT24Result and 255; [masks out the INT 24h code]
-
- For the INT 24h code, use
- I:=INT24Result Shr 8; [same as Div 256, except faster]
-
- INT24Result clears both error codes, so you must assign it to a variable if
- you want to extract both codes:
- J:=INT24Result;
- WriteLn('Turbo IOResult = ',J And 255);
- WriteLn('DOS INT 24h code = ',J Shr 8);
-
- Note that in most cases, errors on character devices (LST and AUX) will not
- return an IOResult, only an INT 24h error code. }
-